package org.example.diary.service;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.example.diary.entity.dao.SysUser;
import org.example.diary.entity.dto.LoginUser;
import org.example.diary.entity.dto.SysUserAddDTO;
import org.example.diary.entity.dto.SysUserDTO;
import org.example.diary.entity.dto.SysUserListDTO;
import org.example.diary.entity.vo.UserListVO;
import org.example.diary.entity.vo.UserVO;
import org.example.diary.enums.BizErrorCode;
import org.example.diary.enums.StatusEnums;
import org.example.diary.exceptions.BizAssertUtil;
import org.example.diary.mapper.UserMapper;
import org.example.diary.util.JwtUtil;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static org.example.diary.constant.Constant.TOKEN_MAP;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private AuthenticationManager authenticationManager;

    @Override
    public UserVO login(SysUserDTO sysUserDTO) {
        String password = sysUserDTO.getPassword();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(sysUserDTO.getUserName(), password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        BizAssertUtil.isTrue(Objects.isNull(authenticate), BizErrorCode.ILLEGAL_PARAM);
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(loginUser.getSysUser(),userVO);

        String token = JwtUtil.createJWT(JSON.toJSONString(loginUser.getSysUser()));
        userVO.setToken(token);
        TOKEN_MAP.put(userVO.getId(),token);
        return userVO;
    }

    @Override
    public String logout(HttpServletRequest request) {
        new SecurityContextLogoutHandler().logout(request, null, null);
        return null;
    }

    @Override
    public PageInfo<UserListVO> userList(SysUserListDTO sysUserListDTO) {
        PageHelper.startPage(sysUserListDTO.getPageNum(), sysUserListDTO.getPageSize());
        List<UserListVO> userList = userMapper.selectUserList(sysUserListDTO);
        return new PageInfo<>(userList);
    }

    @Override
    public String userAdd(SysUserAddDTO sysUserAddDTO) {
        String userName = sysUserAddDTO.getUserName();
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, userName)
                .eq(SysUser::getIsDelete , StatusEnums.NORMAL.getStatus())
        );
        BizAssertUtil.isTrue(!Objects.isNull(sysUser) , BizErrorCode.USER_USERNAME_EXIST);
        String password = sysUserAddDTO.getPassword();

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(password);

        sysUser = new SysUser();
        sysUser.setUsername(userName);
        sysUser.setPassword(encode);
        sysUser.setStatus(StatusEnums.NORMAL.getStatus());
        sysUser.setIsDelete(StatusEnums.NORMAL.getStatus());
        sysUser.setRole(sysUserAddDTO.getRoleId());
        sysUser.setCreateTime(LocalDateTime.now());
        sysUser.setUpdateTime(LocalDateTime.now());

        userMapper.insert(sysUser);
        return null;
    }

    @Override
    public String userIdDel(Integer userId) {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, userId)
                .eq(SysUser::getIsDelete , StatusEnums.NORMAL.getStatus())
        );
        BizAssertUtil.isTrue(Objects.isNull(sysUser) , BizErrorCode.USER_NOT_EXISTS);

        sysUser.setIsDelete(StatusEnums.DELETED.getStatus());
        userMapper.updateById(sysUser);
        return null;
    }

    @Override
    public String userDisable(Integer userId,Integer status) {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, userId)
                .eq(SysUser::getIsDelete , StatusEnums.NORMAL.getStatus())
        );
        BizAssertUtil.isTrue(Objects.isNull(sysUser) , BizErrorCode.USER_NOT_EXISTS);

        sysUser.setStatus(status);
        userMapper.updateById(sysUser);
        return null;
    }

    @Override
    public String userUpdate(SysUserAddDTO sysUserAddDTO) {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, sysUserAddDTO.getId())
                .eq(SysUser::getIsDelete , StatusEnums.NORMAL.getStatus())
        );
        BizAssertUtil.isTrue(Objects.isNull(sysUser) , BizErrorCode.USER_NOT_EXISTS);

        BeanUtil.copyProperties(sysUserAddDTO , sysUser , "id");

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(sysUser.getPassword());
        sysUser.setPassword(encode);

        userMapper.updateById(sysUser);
        return null;
    }

}
